using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Reflection;

using GURUCORE.Framework.Core;
using GURUCORE.Framework.Core.Data;
using GURUCORE.Framework.DataAccess.Provider;
using GURUCORE.Framework.DataAccess.ORMapping.CriteriaMapping;

namespace GURUCORE.Framework.DataAccess.ORMapping
{
    /// <summary>
    /// nested class to read mapped columns as a iterator
    /// </summary>
    internal class ColumnInfoReader
    {
        private Type m_oObjectType;
        private string m_sFieldName;
        private bool m_bIdentity;
        private bool m_bReadOnly;
        private bool m_bSingleQuoted;

        private PropertyInfo[] m_arrProps;

        private int m_nCursor = -1;

        /// <summary>
        /// construct a column reader
        /// </summary>
        /// <param name="p_oObjectType">data object type</param>
        public ColumnInfoReader(Type p_oObjectType)
        {
            m_oObjectType = p_oObjectType;
            m_arrProps = m_oObjectType.GetProperties();
        }

        /// <summary>
        /// current property info
        /// </summary>
        public PropertyInfo PropertyInfo
        {
            get
            {
                return m_arrProps[m_nCursor];
            }
        }

        /// <summary>
        /// current field name
        /// </summary>
        public string FieldName
        {
            get
            {
                return m_sFieldName;
            }
        }

        /// <summary>
        /// current identity flag
        /// </summary>
        public bool Identity
        {
            get
            {
                return m_bIdentity;
            }
        }

        /// <summary>
        /// current readonly flag
        /// </summary>
        public bool ReadOnly
        {
            get
            {
                return m_bReadOnly;
            }
        }

        /// <summary>
        /// current single quoted flag
        /// </summary>
        public bool SingleQuoted
        {
            get
            {
                return m_bSingleQuoted;
            }
        }

        /// <summary>
        /// reset reader at beginning
        /// </summary>
        public void First()
        {
            m_nCursor = -1;
        }

        /// <summary>
        /// read next column
        /// </summary>
        /// <returns>return true if read successfully, else return false</returns>
        public bool Read()
        {
            object[] arrAttributes = new object[0];
            while (arrAttributes.Length == 0)
            {
                m_nCursor++;
                if (m_nCursor >= m_arrProps.Length)
                {
                    return false;
                }
                PropertyInfo oProp = m_arrProps[m_nCursor];
                arrAttributes = oProp.GetCustomAttributes(typeof(PersistencePropertyAttribute), false);
            }
            if (arrAttributes.Length > 0)
            {
                PersistencePropertyAttribute oAttr = (PersistencePropertyAttribute)arrAttributes[0];
                Type tPropType = m_arrProps[m_nCursor].PropertyType;

                m_sFieldName = oAttr.FieldName;
                m_bIdentity = oAttr.Identity;
                m_bReadOnly = oAttr.ReadOnly;
                m_bSingleQuoted = (tPropType == typeof(string)) || (tPropType == typeof(DateTime)) || (tPropType == typeof(char));
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// get property info of specific field
        /// </summary>
        /// <param name="p_sFieldName"></param>
        /// <returns>property info</returns>
        public PropertyInfo GetPropertyInfo(string p_sFieldName)
        {
            foreach (PropertyInfo oProp in m_arrProps)
            {
                if (oProp.Name == p_sFieldName)
                {
                    return oProp;
                }
            }
            return null;
        }
    }
}
